import cherrypy
from cherrypy import Tool, tools
from mako.template import Template
from mako.lookup import TemplateLookup
import os.path 
import urllib
#######################################
## design tool
#######################################
def transform(templatedir=None, templatecache=None, template=None):
    params = cherrypy.response.body
    if templatedir and template and isinstance(params,dict):
        path = os.path.normpath(os.path.join(templatedir,template + ".mak"))
    else:
        return
    mylookup = TemplateLookup(directories=[templatedir])
    mytemplate = Template(filename=path,module_directory=templatecache, lookup=mylookup)
    cherrypy.response.body = mytemplate.render(**params)
    
tools.design = Tool("before_finalize", transform)    

#######################################
## auth tool
#######################################
SESSION_KEY = '_ae_username'

def check_credentials(username, password):
    """Verifies credentials for username and password.
    Returns None on success or a string describing the error on failure"""
    session=main.Session()
    
    users = session.query(model.User).filter_by(name=username).all()
    session.close()
    if len(users):
        user=users[0]
    else:
        return u"Incorrect user."
    if user.checkPassword(password):
        return None
    else:
        return u"Incorrect password."

def check_auth(*args, **kwargs):
    """A tool that looks in config for 'auth.require'. If found and it
    is not None, a login is required and the entry is evaluated as alist of
    conditions that the user must fulfill"""
    conditions = cherrypy.request.config.get('auth.require', None)
    # format GET params
    get_parmas = urllib.quote(cherrypy.request.request_line.split()[1])
    if conditions is not None:
        username = cherrypy.session.get(SESSION_KEY)
        if username:
            cherrypy.request.login = username
            for condition in conditions:
                # A condition is just a callable that returns true orfalse
                if not condition():
                    # Send old page as from_page parameter
                    raise cherrypy.HTTPRedirect("/auth/login?from_page=%s" % get_parmas)
        else:
            # Send old page as from_page parameter
            raise cherrypy.HTTPRedirect("/auth/login?from_page=%s" %get_parmas) 
    
tools.auth = Tool('before_handler', check_auth)

def require(*conditions):
    """A decorator that appends conditions to the auth.require config
    variable."""
    def decorate(f):
        if not hasattr(f, '_cp_config'):
            f._cp_config = dict()
        if 'auth.require' not in f._cp_config:
            f._cp_config['auth.require'] = []
        f._cp_config['auth.require'].extend(conditions)
        return f
    return decorate

#######################################
## auth controller
#######################################

class AuthController(object):
    
    def on_login(self, username):
        """Called on successful login"""
    
    def on_logout(self, username):
        """Called on logout"""
    
    def get_loginform(self, username, msg="Enter login information", from_page="/"):
        return """<html><body>
            <form method="post" action="/auth/login">
            <input type="hidden" name="from_page" value="%(from_page)s" />
            %(msg)s<br />
            Username: <input type="text" name="username" value="%(username)s" /><br />
            Password: <input type="password" name="password" /><br />
            <input type="submit" value="Log in" />
        </body></html>""" % locals()
    
    @cherrypy.expose
    def login(self, username=None, password=None, from_page="/"):
        if username is None or password is None:
            return self.get_loginform("", from_page=from_page)
        
        error_msg = check_credentials(username, password)
        if error_msg:
            return self.get_loginform(username, error_msg, from_page)
        else:
            cherrypy.session[SESSION_KEY] = cherrypy.request.login = username
            self.on_login(username)
            raise cherrypy.HTTPRedirect(from_page or "/")
    
    @cherrypy.expose
    def logout(self, from_page="/"):
        sess = cherrypy.session
        username = sess.get(SESSION_KEY, None)
        sess[SESSION_KEY] = None
        if username:
            cherrypy.request.login = None
            self.on_logout(username)
        raise cherrypy.HTTPRedirect(from_page or "/")

#######################################
## controller
#######################################
class Root(object):
    auth = AuthController()

    @cherrypy.expose
    @require()
    @cherrypy.tools.design(template='temp')
    def index(self):
        return dict(name='Maurizio',menu=[("menu1","/link/to/menu1"),("menu2","/link/to/menu2")])
    def test(self):
        return "pagina test!"
    test.exposed = True


#read config
from config import AlEarthConfig
import model
configuration = AlEarthConfig()
homedir = configuration.get("server","homedir")
cherrypy_config={
    "global" : {
                "server.socket_port" : configuration.getint('server','port'),
                "server.thread_pool" : 10,
                "tools.sessions.on" : True,
                "tools.auth.on": True,
                "tools.staticdir.root" : os.path.join(homedir,"static"),
                "tools.design.templatedir" : os.path.join(homedir,"templates"),
                "tools.design.templatecache" : os.path.join(homedir,"temp_cache")
               },
    "/css" :   {
                "tools.staticdir.on" : True,
                "tools.staticdir.dir" : "css"
               },
    "/js" :    {
                "tools.staticdir.on" : True,
                "tools.staticdir.dir" : "js"
               }
    }


main = model.Main(os.path.join(homedir,'al_earth.db'))

if __name__=="__main__":
    cherrypy.quickstart(Root(), '/', cherrypy_config)
